﻿using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;

namespace ZhuXingFamilys.test
{
    [Transaction(TransactionMode.Manual)]
    public class testcommand : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {

            
            UIApplication uiApp = commandData.Application;
            Autodesk.Revit.ApplicationServices.Application app = uiApp.Application;
            Document doc = uiApp.ActiveUIDocument.Document;
            //**以上三行为获取DB级别和UI级别文档（以后会经常见到）

            Transaction trans = new Transaction(doc, "自动扣减");//新建一个事务
            trans.Start();//开始事务
            Form1 form1 = new Form1();//运行弹出窗口程序
            //if (form1.ShowDialog() == DialogResult.OK)//将窗口输入的内容返回到主程序
            //{
            //}
            string loucen = "";//将窗口输入内容赋值给新建的变量 ‘loucen’

            //获得所有结构柱图元
            FilteredElementCollector JGZfilteredElements = new FilteredElementCollector(doc);
            //新建一个收集器 ‘JGZfilteredElements’
            JGZfilteredElements.OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_StructuralColumns);
            //对所有图元应用过滤器‘.OfClass(typeof(FamilyInstance))’和‘.OfCategory(BuiltInCategory.OST_StructuralColumns)’
            //得到所有的结构柱图元，并存到收集器中
            var strcloumnElement = from element in JGZfilteredElements
                                   where element.get_Parameter(BuiltInParameter.DOOR_NUMBER).AsString() == loucen
                                   select element;
            IList<Element> strcloumn = strcloumnElement.ToList<Element>();//得到所有标记值为‘loucen’的结构柱
            //以上前三行为LINQ语法，从所有结构柱图元中获取 标记值 等于 窗口输入值 的图元
            //意思是柱子的标记如果是‘1’，那么在窗口输入‘1’的话，这个柱子会被过滤出来

            //获得所有结构板图元（同获得所有结构柱图元）
            FilteredElementCollector BfilteredElements = new FilteredElementCollector(doc);
            BfilteredElements.OfClass(typeof(Floor));
            var strfloorElement = from element in BfilteredElements
                                  where element.get_Parameter(BuiltInParameter.DOOR_NUMBER).AsString() == loucen
                                  select element;
            IList<Element> floor = strfloorElement.ToList<Element>();

            //获得所有梁图元（同获得所有结构柱图元）
            FilteredElementCollector LfilteredElements = new FilteredElementCollector(doc);
            LfilteredElements.OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_StructuralFraming);
            var strframingElement = from element in LfilteredElements
                                    where element.get_Parameter(BuiltInParameter.DOOR_NUMBER).AsString() == loucen
                                    select element;
            IList<Element> beam = strframingElement.ToList<Element>();

            //获得所有墙图元
            FilteredElementCollector QfilteredElements = new FilteredElementCollector(doc);
            QfilteredElements.OfClass(typeof(Wall));
            var wallElement = from element in QfilteredElements
                              where element.get_Parameter(BuiltInParameter.DOOR_NUMBER).AsString() == loucen
                              select element;
            IList<Element> wall = wallElement.ToList<Element>();
            //（以上部分同获得所有结构柱图元）
            IList<Element> strwall = new List<Element>();//新建一个结构墙存储集合
            IList<Element> arcwall = new List<Element>();//新建一个建筑墙存储集合
            foreach (Element wall1 in wall)//遍历每一个墙
            {
                string strwallparameter = wall1.get_Parameter(BuiltInParameter.WALL_STRUCTURAL_SIGNIFICANT).AsValueString();
                //得到墙的‘BuiltInParameter.WALL_STRUCTURAL_SIGNIFICANT’属性（是否为结构）赋值给变量 ‘strwallparameter’
                if (strwallparameter == "是")//属性值为‘是’，将这个墙图元放到结构墙存储集合中
                    strwall.Add(wall1);
                else//否则放到建筑墙存储集合
                    arcwall.Add(wall1);
            }
            System.Windows.MessageBox.Show("该层模型共包含有:\n" + strcloumn.Count + "个结构柱\n" + floor.Count + "个结构板\n" + beam.Count
                + "个结构梁\n" + strwall.Count + "个结构墙\n" + arcwall.Count + "个建筑墙\n进行自动扣减,请耐心等待...");
            //弹出对话框

            //结构柱扣结构板
            foreach (Element strcloumn1 in strcloumn)//遍历，从结构柱存储集合取出每一个结构柱
            {
                foreach (Element floor1 in floor)//遍历，从板存储集合取出每一个板
                {
                    QJ(doc, strcloumn1, floor1);//调用‘QJ’方法（在末尾），‘QJ’方法的功能是连接并扣减模型
                }
            }

            //结构柱扣梁（同结构柱扣结构板）
            foreach (Element strcloumn1 in strcloumn)
            {
                foreach (Element beam1 in beam)
                {
                    QJ(doc, strcloumn1, beam1);
                }
            }

            //结构柱扣墙（同结构柱扣结构板）
            foreach (Element strcloumn1 in strcloumn)
            {
                foreach (Element wall1 in wall)
                {
                    QJ(doc, strcloumn1, wall1);
                }
            }

            //结构墙扣板（同结构柱扣结构板）
            foreach (Element strwall1 in strwall)
            {
                foreach (Element floor1 in floor)
                {
                    QJ(doc, strwall1, floor1);
                }
            }

            //结构墙扣梁（同结构柱扣结构板）
            foreach (Element strwall1 in strwall)
            {
                foreach (Element beam1 in beam)
                {
                    QJ(doc, strwall1, beam1);
                }
            }

            //结构墙扣建筑墙（同结构柱扣结构板）
            foreach (Element strwall1 in strwall)
            {
                foreach (Element arcwall1 in arcwall)
                {
                    QJ(doc, strwall1, arcwall1);
                }
            }

            //结构板扣梁（同结构柱扣结构板）
            foreach (Element floor1 in floor)
            {
                foreach (Element beam1 in beam)
                {
                    QJ(doc, floor1, beam1);
                }
            }

            //板扣建筑墙（同结构柱扣结构板）
            foreach (Element floor1 in floor)
            {
                foreach (Element arcwall1 in arcwall)
                {
                    QJ(doc, floor1, arcwall1);
                }
            }

            //梁扣建筑墙（同结构柱扣结构板）
            foreach (Element beam1 in beam)
            {
                foreach (Element arcwall1 in arcwall)
                {
                    QJ(doc, beam1, arcwall1);
                }
            }

            System.Windows.MessageBox.Show("***************************\n该楼层构件已自动扣减完成.\n***************************\n");
            //弹出对话框

            trans.Commit();//结束事务并提交
            return Result.Succeeded;//若成功执行则返回结果并结束程序
        }

        //‘QJ’方法，被主程序调用
        public void QJ(Document doc, Element a, Element b)//被调用的扣减程序
        {
            if (JoinGeometryUtils.AreElementsJoined(doc, a, b))//判断a、b是否连接（例：结构柱扣梁中，a、b在这里代表的是结构柱与梁）
            {
                JoinGeometryUtils.UnjoinGeometry(doc, a, b);//a、b若已经连接则取消连接
            }
            try
            {
                JoinGeometryUtils.JoinGeometry(doc, a, b);//连接a、b
                if (!JoinGeometryUtils.IsCuttingElementInJoin(doc, a, b))//判断扣减效果是否为a扣减b（前面的会扣减后面的）
                {
                    JoinGeometryUtils.SwitchJoinOrder(doc, a, b);//否则的话则转换为a扣减b
                }
            }
            catch (Exception e)
            {
            }
        }//调用结束，返回扣减成功的命令
    }
}
